home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 202_01.zip / KED2.C < prev    next >
Text File  |  1993-04-01  |  25KB  |  712 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <ked.h>
  4.  
  5.  
  6. getchr()   /* low-level character input */
  7. {
  8.      char c;
  9.  
  10.      c = getch();
  11.      putch(c);
  12.      return c;
  13. }
  14.  
  15.  
  16. int lower(c)
  17. char c;
  18. {
  19.      return isupper(c) ? c+32 : c;
  20. }
  21.  
  22. int upper(c)
  23. char c;
  24. {
  25.      return islower(c) ? c-32 : c;
  26. }
  27.  
  28.  
  29. readin(w)   /* find location of command in comm array or symbol table */
  30. char w[];
  31. {
  32.           int c,i,l,m;
  33.  
  34.           do {
  35.             inputs(w);
  36.             if ((m = match(w,comm,MAXCOMM)) != NOMATCH)
  37.                return m;              
  38.             if (m == NOMATCH && last != first && p != pr) {
  39.                l = pr->lastin;
  40.                if (l == 15) 
  41.                    l = last;
  42.                for (i = first; i != l; i = new[i].nextin)
  43.                     if ((c = strcomp(w,new[i].defname)) == 0) 
  44.                        return ( -i - 1);
  45.             }          
  46.             printf("INVALID COMMAND. TYPE MN TO SEE MENU.\n?");
  47.           } while (m == NOMATCH);
  48. }
  49.  
  50.  
  51.  
  52. menu()           /* print updated menu */
  53. {
  54.           int i;
  55.  
  56.           printf("THE FOLLOWING IS A LIST OF VALID ");
  57.           printf("COMMANDS FOR THIS EDITOR.\n\n");
  58.           printf("  INSTRUCTIONS\n");   
  59.           printf("m          move\n");
  60.           printf("tl         turnleft\n");
  61.           printf("pi         pickbeeper\n");
  62.           printf("pu         putbeeper\n");
  63.           printf("to         turnoff\n");
  64.           printf("b          BEGIN\n");
  65.           printf("bx         BEGINNING-OF-EXECUTION\n");
  66.           printf("nd         END\n");
  67.           printf("ndc        end construct\n");
  68.           printf("ndx        END-OF-EXECUTION\n");
  69.           printf("if         IF\n");
  70.           printf("el         ELSE\n");
  71.           printf("it         ITERATE\n");
  72.           printf("wh         WHILE\n");
  73.           printf("df         DEFINE-NEW-INSTRUCTION\n");
  74.           printf("\nTYPE ANY KEY TO CONTINUE.\n");
  75.           getchr();
  76.           if (last != first) {   /* any valid sym tab entries? */
  77.            printf("\n  USER-DEFINED COMMANDS\n");
  78.            for (i = first; i != last; i = new[i].nextin)
  79.                 printf("%s\n", new[i].defname);  
  80.           }
  81.           printf("\n  EDIT COMMANDS\n");      
  82.           printf("n          move pointer to next instruction\n");
  83.           printf("nc         move pointer to next construct\n");
  84.           printf("n-         move pointer to previous instruction\n");
  85.           printf("n--        move pointer back 10 lines\n"); 
  86.           printf("d          delete current instruction\n");
  87.           printf("c          print current line\n");
  88.           printf("p          print next 20 lines\n");
  89.           printf("i          insert new instruction before current one\n");
  90.           printf("t          move pointer to the first line\n");
  91.           printf("l          list the rest of the program\n");
  92.           printf("s          save the program\n");
  93.           printf("mn         print an updated menu\n");
  94.           printf("q          quit the edit program\n");
  95.           printf("\nTYPE ANY KEY TO CONTINUE.\n");
  96.           getchr();
  97.           printf("\n  TESTS\n");
  98.           printf("n          facing-north\n");
  99.           printf("nn         not-facing-north\n");
  100.           printf("s          facing-south\n");
  101.           printf("ns         not-facing-south\n");
  102.           printf("e          facing-east\n");
  103.           printf("ne         not-facing-east\n");
  104.           printf("w          facing-west\n");
  105.           printf("nw         not-facing-west\n");
  106.           printf("c          next-to-a-beeper (beeper on corner)\n");
  107.           printf("nc         not-next-to-a-beeper\n");
  108.           printf("b          any-beepers-in-beeper-bag\n");
  109.           printf("nb         no-beepers-in-beeper bag\n");
  110.           printf("f          front-is-clear\n");
  111.           printf("nf         front-is-blocked\n");
  112.           printf("l          left-is-clear\n");
  113.           printf("nl         left-is-blocked\n");
  114.           printf("r          right-is-clear\n");
  115.           printf("nr         right-is-blocked\n");
  116. }
  117.  
  118. createtree()                      /* reads information from old file1 */
  119. {
  120.            int i,in,d,fn,fs,b,t,l;
  121.            char *malloc();
  122.  
  123.            fscanf(fptr1, "%d %d %d %d %d %d %d %d",
  124.                   &i,&in,&d,&fn,&fs,&b,&t,&l);
  125.            pr = NULL;
  126.            p = (struct tnode *)malloc(24);
  127.            tree(i,in,d,fn,fs,b,t,l);              /* store first node */
  128.            root = p;
  129.            p = root->sub = (struct tnode *)malloc(24);
  130.            pr = root;
  131.            fscanf(fptr1, "%d %d %d %d %d %d %d %d",
  132.                   &i,&in,&d,&fn,&fs,&b,&t,&l);
  133.            while (i != NDX && i != CPMEOF && i != EOF) { 
  134.                createnode(fptr1,i,in,d,fn,fs,b,t,l);    
  135.                fscanf(fptr1, "%d %d %d %d %d %d %d %d",
  136.                       &i,&in,&d,&fn,&fs,&b,&t,&l);
  137.            }
  138.            endcons();
  139.            tree(i,in,d,fn,fs,b,t,l);
  140.            pr = p;
  141.            fclose(fptr1);        
  142. }
  143.  
  144.  
  145. createnode(fptr1,i,in,d,fn,fs,b,t,l)    /* restores nodes for parse tree */
  146. FILE *fptr1;
  147. int i,in,d,fn,fs,b,t,l;
  148. {
  149.           int j;
  150.           char w[MAXLINE];
  151.           struct tnode *allocp();
  152.  
  153.           if (d == NEWINSTR && pr->instr != DEF) {
  154.               i = reloc[i];                   /* set up array to convert */
  155.               j = 0;                              /* old symb tab to new */
  156.               while (new[i].loc[j] != NULL)
  157.                      j++;
  158.               new[i].loc[j] = p;
  159.               new [i].loc[++j] = NULL;
  160.               if (l != 15)
  161.                  l = last;
  162.               tree(i,in,d,fn,fs,b,t,l);
  163.               p = p->next = allocp();
  164.           } else switch (i) { 
  165.                  case 0:            /* move */
  166.                  case 1:            /* turnleft */
  167.                  case 2:            /* pickbeeper */
  168.                  case 3:            /* putbeeper */
  169.                  case 4:            /* turnoff */
  170.                     while (in < pr->indent)
  171.                            endcons();
  172.                     if (l != 15)
  173.                        l = last;
  174.                     tree(i,in,d,fn,fs,b,t,l);
  175.                     p = p->next = allocp();
  176.                     break;
  177.                 case 5:             /* BEGIN */
  178.                 case 7:             /* BEGINNING-OF-EXECUTION */
  179.                 case 13:            /* ELSE */
  180.                    if (l != 15)
  181.                       l = last;
  182.                    tree(i,in,d,fn,fs,b,t,l);
  183.                    p = p->sub = allocp();
  184.                    break;
  185.                case 8:              /* END */
  186.                   if (l != 15)
  187.                      l = last;
  188.                   tree(i,in,d,fn,fs,b,t,l);
  189.                   p = p->next = allocp();
  190.                   endcons();
  191.                   break;
  192.                case 11:             /* IF */
  193.                   while (in < pr->indent)
  194.                       endcons();
  195.                   if (l != 15)
  196.                      l = last;
  197.                   tree(i,in,d,fn,fs,b,t,l);
  198.                   p = p->sub = allocp();
  199.                   fscanf(fptr1,"%d %d %d %d %d %d %d %d",
  200.                          &i,&in,&d,&fn,&fs,&b,&t,&l);         /* get test */
  201.                   if (l != 15)
  202.                      l = last;
  203.                   tree(i,in,d,fn,fs,b,t,l);
  204.                   p = p->sub = allocp();
  205.                   fscanf(fptr1, "%d %d %d %d %d %d %d %d",
  206.                          &i,&in,&d,&fn,&fs,&b,&t,&l);         /* get THEN */
  207.                   if (l != 15)
  208.                      l = last;
  209.                   tree(i,in,d,fn,fs,b,t,l);
  210.                   p = p->sub = allocp();
  211.                   break;
  212.                case 14:               /* ITERATE */
  213.                case 15:               /* WHILE */
  214.                   while (in < pr->indent)
  215.                       endcons();
  216.                   if (l != 15)
  217.                      l = last;
  218.                   tree(i,in,d,fn,fs,b,t,l);
  219.                   p = p->sub = allocp();
  220.                   fscanf(fptr1,"%d %d %d %d %d %d %d %d",
  221.                          &i,&in,&d,&fn,&fs,&b,&t,&l);      /* get test or */
  222.                   if (l != 15)                                 /* pos int */
  223.                      l = last;
  224.                   tree(i,in,d,fn,fs,b,t,l);                   
  225.                   p = p->sub = allocp();
  226.                   break;
  227.                case 16:             /* DEFINE-NEW-INSTRUCTION */
  228.                   tree(i,in,d,fn,fs,b,t,last);
  229.                   p = p->sub = allocp();
  230.                   fscanf(fptr1,"%d %d %d %d %d %d %d %d",
  231.                          &i,&in,&d,&fn,&fs,&b,&t,&l);      /* get new name */
  232.                   i = reloc[i] = last;                        /* translate */
  233.                   j = 0;                              /* sym tab subscript */
  234.                   while ((w[j++] = getc(fptr1)) != '\n')
  235.                       ;
  236.                   j -= 3;
  237.                   w[j] = '\0';
  238.                   strcpy(new[i].defname,w);
  239.                   new[i].nextin = last + 1; /* store next ref in sym table */
  240.                   tree(i,in,d,fn,fs,b,t,last);
  241.                   p = p->sub = allocp();
  242.                   break;
  243.                }
  244. }   
  245.  
  246.  
  247. insertinstr()     /* prepare to add instructions in insert mode */
  248. {
  249.         
  250.           struct tnode *allocp(), *conbegin(), *advance();
  251.  
  252.           insert = 1;
  253.           insertnode = curr;
  254.           if ((curr->instr == NDX ||        /* find previous construct */
  255.                curr->instr == ND) && curr->del !=  NEWINSTR) {
  256.               p = curr->prev;
  257.               if (p->cons != 1)
  258.                  while (p->indent > curr->indent + 1)
  259.                      p = conbegin(p);
  260.           } else p = curr->prec;
  261.           if (p->instr == IFF) {     /* set THEN as start of construct */
  262.              p = advance(p);                /* so ELSE can be inserted */
  263.              p = advance(p);
  264.           }
  265.           ins = p->indent;         /* final indent level for construct */
  266.           if ((p->instr == BX || p->instr == BEG || p->instr == BEPGM)
  267.                && p->del != NEWINSTR)
  268.                ++ins;
  269.           if (insertnode == p->sub ||
  270.              (p->instr == BX && p->del != NEWINSTR)) 
  271.               p = p->sub = allocp();           /* set up links to next */
  272.           else {                                   /* node to be added */
  273.                p = p->next = allocp();
  274.                temp = insertnode->prev;  
  275.                temp->next = p;
  276.           }
  277. }
  278.  
  279.  
  280. endinsert()        /* exit insert mode */
  281. {
  282.  
  283.           if (insert) {
  284.               if (pr->instr == THEN) 
  285.                  if (p == pr->sub)
  286.                     printf("PLEASE COMPLETE CONSTRUCT\n");
  287.                  else endcons();
  288.               if (pr->indent > ins)
  289.                  printf("PLEASE COMPLETE CONSTRUCT\n");
  290.               else {
  291.                  insert = 0;
  292.                  insertnode->prec = pr;
  293.                  if (tempend != NULL) {            /* if a node has been */
  294.                      tempend->next = insertnode;   /* inserted link last */
  295.                      insertnode->prev = tempend;          /* instruction */
  296.                      tempend = NULL;
  297.                  } else if (temp != NULL)           /* otherwise restore */
  298.                             temp->next = insertnode;        /* old links */
  299.                         else if (p == pr->next)
  300.                                  pr->next = insertnode;
  301.                              else pr->sub = insertnode;
  302.                  temp = NULL;  
  303.                  free((char *)p);
  304.                  p = pr;
  305.                  curr = insertnode;
  306.               }
  307.          }
  308.  
  309.  
  310. delete()                /* delete or replace current instruction */
  311. {
  312.           int c;
  313.  
  314.           switch(curr->del) {
  315.           case 0:       /* reserved word */
  316.              printf("DELETE ENTIRE CONSTRUCT? (Y/N)\n");
  317.              if ((c = upper(getchr())) == 'Y')
  318.                   deletecon();
  319.              else printf("\n");
  320.              break;
  321.           case 1:       /* simple instruction */
  322.              demalloc(curr,curr->next);
  323.              break;
  324.           case 2:       /* test */
  325.              prompt("TYPE REPLACEMENT ",1,"",5,0);
  326.              curr->instr = getest();
  327.              print(curr->prev,stdout);
  328.              print(curr,stdout);
  329.              break;
  330.           case 3:       /* positive number */
  331.              prompt("TYPE REPLACEMENT ",2,"",16,0);
  332.              curr->instr = getint();
  333.              print(curr->prev,stdout);
  334.              print(curr,stdout); 
  335.              break;
  336.           case 4:       /* new name */
  337.              if (curr->prev->instr == DEF) {
  338.                  prompt("TYPE REPLACEMENT ",4,"",9,0);
  339.                  getnew(curr->instr);
  340.                  print(curr->prev,stdout);
  341.                  print(curr,stdout); 
  342.              } else demalloc(curr,curr->next);
  343.              break;
  344.           case 5:       /* BEGINNING-OF-PROGRAM, BX, NDX */
  345.              printf("CAN'T BE DELETED\n?");
  346.              break;
  347.       }
  348. }
  349.  
  350.  
  351. deletecon()       /* locate start and end of current construct */
  352. {
  353.  
  354.           struct tnode *ptr1, *ptr2, *conbegin(), *conend();
  355.  
  356.           if (curr->instr == THEN || curr->cons != 1)
  357.               ptr1 = conbegin(curr);       /* locate start of construct */
  358.           else ptr1 = curr; 
  359.           if (ptr1->instr == DEF)          /* delete all references for */
  360.               deletenewin(ptr1->sub->instr);           /* defined instr */
  361.           ptr2 = conend(ptr1);               /* locate end of construct */
  362.           demalloc(ptr1,ptr2);
  363. }
  364.  
  365.  
  366. struct tnode *conbegin(ptr)       /* locates start of current construct */
  367. struct tnode *ptr;
  368. {
  369.           int in;
  370.  
  371.           if (ptr->instr == ND && ptr->del != NEWINSTR) {
  372.               in = ptr->indent;
  373.               while ((ptr = ptr->prev)->indent > in)
  374.                        ;
  375.           }
  376.           while ((ptr = ptr->prev)->cons != 1 || ptr->instr == THEN)
  377.              ;   
  378.           return ptr;
  379. }
  380.  
  381.  
  382. struct tnode *conend(ptr)        /* locates end of current construct */
  383. struct tnode *ptr;
  384. {
  385.           int d,in;
  386.           struct tnode *advance();
  387.  
  388.           in = ptr->indent;
  389.           if (ptr != endof)
  390.              ptr = advance(ptr);
  391.           while (ptr != endof && (ptr->indent > in ||
  392.                  (d = ptr->del) == TEST || d == POSINT || d == NEWINSTR)) 
  393.               ptr = advance(ptr);
  394.           if (ptr == endof && (ptr->indent > in ||
  395.               (d = ptr->del) == TEST || d == POSINT || d == NEWINSTR))
  396.               ptr = p;
  397.           return ptr; 
  398.  
  399. }
  400.  
  401.  
  402. deletenewin(i)                /* removes user-defined instruction */
  403. int i;
  404. {
  405.  
  406.           int j;
  407.           struct tnode *ptr;
  408.  
  409.           j = 0;
  410.           while ((ptr = new[i].loc[j]) != NULL) { 
  411.               demalloc(ptr,ptr->next);        /* locate and delete */
  412.               j++;                                 /* uses in pgm */
  413.           }
  414.           j = first;
  415.           if (j != i) {
  416.              while (new[j].nextin != i)             /* remove sym */
  417.                  j = new[j].nextin ;          /* table references */
  418.              new[j].nextin = new[i].nextin;
  419.           } else if (new[first].nextin == last)
  420.                      --last;
  421.                  else first = new[i].nextin;
  422. }
  423.  
  424.  
  425.  
  426. demalloc(ptr1,ptr2)                 /* free space from ptr1 up to ptr2 */
  427. struct tnode *ptr1,*ptr2;
  428. {
  429.  
  430.           struct tnode *ptr;
  431.       
  432.           printf("\n");
  433.           if (ptr2->instr != NDX || ptr2->del == NEWINSTR)
  434.               ptr2->prec = ptr1->prec;        /* set up links between */
  435.           curr = ptr2;                        /* ptr2 & ptr1's parent */
  436.           ptr = ptr2->prev = ptr1->prev;
  437.           if (ptr1 == ptr->sub &&
  438.              (ptr2->instr != NDX || ptr2->del == NEWINSTR))
  439.               ptr->sub = ptr2;
  440.           else { 
  441.              ptr->next = ptr2;
  442.              if (ptr2->instr == NDX && ptr2->del != NEWINSTR)
  443.                  ptr->sub = NULL;
  444.           }
  445.           while (ptr1 != ptr2) {               /* deallocate nodes in */
  446.               ptr = ptr1;                     /* succession and print */
  447.               if (ptr1->sub != NULL)
  448.                   ptr1 = ptr1->sub;
  449.               else if (ptr1->next != NULL)
  450.                        ptr1 = ptr1->next;
  451.               print(ptr,stdout);
  452.               free((char *)ptr);
  453.           }
  454.           if (ptr2 == p && p != pr) {              /* if last line of */
  455.               endof = temp = curr = ptr1->prev;   /* pgm, set new eof */ 
  456.               pr = ptr1->prec;
  457.               temp->next = p;
  458.           }       
  459. }
  460.  
  461.  
  462. putintable(i)     /* add new name to symbol table */
  463. int i;
  464. {
  465.           int j,k;
  466.  
  467.           if (insert && insertnode->instr == DEF) {
  468.               j = insertnode->sub->instr;         /* if inserting before */
  469.               new[i].nextin = j;                    /* DEF locate proper */
  470.               for (k = first; new[k].nextin != last;)     /* position in */
  471.                    k = new[k].nextin;                     /* linked list */
  472.               new[k].nextin = last + 1;
  473.               if (j == first)
  474.                   first = i;
  475.               else {
  476.                  for (k = first; new[k].nextin != j;)
  477.                       k = new[k].nextin;
  478.                  new[k].nextin = i;
  479.              }                            /* otherwise add as last entry */
  480.           } else new[i].nextin = last + 1;
  481. }   
  482.  
  483.  
  484. savetree(p,argv)         /* write parse tree to file1, text to file2 */
  485. struct tnode *p;
  486. char **argv;
  487. {
  488.           struct tnode *advance(); 
  489.  
  490.           fptr1 = fopen(argv[1],"w");         /* open both files */
  491.           fptr2 = fopen(argv[2],"w");         /* for writing */
  492.           while (p != endof) {
  493.               fprintf(fptr1, "%d %d %d %d %d %d %d %d \n",   /*codes */
  494.                     p->instr,p->indent,p->del,p->nfollow,/* in file1 */
  495.                     p->sfollow,p->comp,p->cons,p->lastin);
  496.               print(p,fptr2);                       /* text in file2 */
  497.               if (p->instr == DEF && p->del == 0) {
  498.                   p = advance(p);
  499.                   fprintf(fptr1,"%d %d %d %d %d %d %d %d \n",
  500.                           p->instr,p->indent,p->del,p->nfollow,
  501.                           p->sfollow,p->comp,p->cons,p->lastin);
  502.                   print(p,fptr2);
  503.                   fprintf(fptr1,"%s \n",new[p->instr].defname);
  504.               }
  505.               p = advance(p);      
  506.            } 
  507.            fprintf(fptr1, "%d %d %d %d %d %d %d %d \n",
  508.                    9,1,5,4,4,0,2,10);
  509.            print(p,fptr2);
  510.            putc(CPMEOF,fptr1);    putc(CPMEOF,fptr2);
  511.            fclose(fptr1);         fclose(fptr2);
  512.          
  513. }
  514.  
  515.  
  516.  
  517. tree(i,in,d,fn,fs,b,t,l)    /* store instruction codes in parse tree */
  518. int i,in,d,fn,fs,b,t,l;
  519. {
  520.          p->sub = NULL;
  521.          p->next = NULL;
  522.          p->prec = pr;
  523.          if (pr->sub != NULL && p == pr->next) {
  524.              p->prev = temp;                       /* set up link to */
  525.              temp = NULL;                    /* previous instruction */
  526.          } else p->prev = pr;
  527.          p->instr = i;
  528.          p->indent = in;
  529.          p->del = d;
  530.          p->nfollow = fn;
  531.          p->sfollow = fs;
  532.          p->comp = b;
  533.          p->cons = t;
  534.          p->lastin = l;
  535.          if (insert)
  536.              tempend = p;     /* last node inserted */
  537.          else endof = p;      /* last node added (eof) */
  538. }
  539.  
  540.  
  541. struct tnode *allocp()      /* get space for next node */
  542. {
  543.           char *malloc();
  544.           struct tnode *ptr;
  545.  
  546.           ptr = (struct tnode *)malloc(24);
  547.           curr = p;
  548.           pr = p;
  549.           return ptr;
  550. }
  551.  
  552.  
  553. inputs(w)         /* read in next command */
  554. char w[];
  555. {
  556.           int i,m;
  557.           char c;
  558.  
  559.           m = 0;
  560.           i = 0;
  561.           while ((c = w[i++] = lower(getchr())) != '\r')
  562.               if ((c > 'z' || c < 'a') && (c > '9' || c < '0') && c != '-') 
  563.                 m = ERROR;
  564.           w[--i] = '\0';
  565.           return m;
  566. }
  567.  
  568.  
  569. match(w,s,maxx)          /* compares string to array element */
  570. char w[], *s[];
  571. int maxx;
  572. {
  573.           int c,i;
  574.  
  575.           for (i = 0; i < maxx; i++) {
  576.             c = strcomp(w,s[i]);
  577.             if (c == 0)                 /* if match, return */
  578.                 return i;                /* array subscript */
  579.           }
  580.           return NOMATCH;            /* else return NOMATCH */
  581. }
  582.  
  583.  
  584. prompt(mess1,num1,mess2,num2,i)       /* prompt for next instruction */
  585. char *mess1,*mess2;
  586. int num1, num2,i;
  587. {
  588.           int j;
  589.  
  590.           printf("%s",mess1);                  /* print first string */
  591.           switch(num1) {           /* print desired instruction type */  
  592.           case 1:
  593.              printf("<test>");
  594.              break;
  595.           case 2:
  596.              printf("<positive-number>");
  597.              break;
  598.           case 3:
  599.              for (j = 0; j < curr->indent;
  600.                          printf("  "), j++);
  601.              if (i == ND || i == NDC) {
  602.                 printf("\b");
  603.                 printf("\b");
  604.              }
  605.              printf("<instruction>");
  606.              break;
  607.           case 4:
  608.              printf("<new-name>");
  609.              break;
  610.           }
  611.           printf("%s",mess2);            /* print second string */
  612.           for (; num2-- > 0; printf("\b"))
  613.             ;
  614. }
  615.  
  616.  
  617. struct tnode *advance(ptr)         /* point to next line or eof */
  618. struct tnode *ptr;
  619. {
  620.           if (ptr->sub != NULL)
  621.               ptr = ptr->sub;
  622.           else if (ptr->next != NULL)
  623.                    ptr = ptr->next;
  624.           return ptr;
  625. }
  626.  
  627.  
  628. checkin(valid)   /* correct location for an instruction? */
  629. int *valid;
  630. {
  631.           int in;
  632.  
  633.           *valid = 1;
  634.           if (p == pr && !insert) {  /* if NDX added, must insert */
  635.               printf("INSERT ONLY\n?");
  636.               *valid = 0;
  637.           } else { 
  638.                if (pr->instr == THEN && p!= pr->sub) {
  639.                    endcons();               /* end THEN construct */
  640.                    if (insert)            /* since ELSE not added */
  641.                       ins = pr->indent;
  642.                }
  643.                if (pr->nfollow == 0 &&           
  644.                           p == pr->next)
  645.                    in = pr->indent;         
  646.                else if (pr->sfollow == 0 && 
  647.                                p == pr->sub)
  648.                         in = pr->indent + 1;
  649.                      else { 
  650.                         *valid = 0;
  651.                         printf("BAD LOCATION FOR COMMAND. ");
  652.                         printf("TYPE MN TO SEE MENU.\n?");
  653.                      }
  654.             }           
  655.           return in;
  656. }
  657.  
  658.  
  659. checkcomp(valid)         /* compound statement? */
  660. int *valid;
  661. {
  662.           int b;
  663.  
  664.           if (pr->comp == 2) {       /* if 2nd instr added without BEGIN */
  665.               *valid = 0;
  666.               printf("STRUCTURE NOT A COMPOUND STATEMENT\n?");
  667.           } else if (pr->comp == 1)  /* if 1st instr added without BEGIN */
  668.                      b = 2;            /* set warning for future entries */
  669.                  else b = pr->comp;
  670.           return b;
  671. }
  672.  
  673.  
  674.  
  675. endcons()         /* end construct */
  676. {  
  677.           int in;
  678.           char *malloc();
  679.   
  680.           if (pr->indent == 1)     /* only BX, NDX indented 1 level */
  681.               printf("LAST POSSIBLE LEVEL\n");   
  682.           else {
  683.              if (temp->next != p     /* keep last instr in previous */
  684.                  || temp == NULL)               
  685.                  temp = pr;            /* construct if NDC repeated */
  686.              do {
  687.               in = pr->indent;
  688.               while ((pr = pr->prev)->cons != 1 /* go back to start */
  689.                       || pr->indent >= in);         /* of construct */
  690.              } while (pr->instr == ELS);               /* skip ELSE */
  691.              if (pr->instr == DEF)          /* if DEF ended add new */
  692.                  last++;                         /* name to sym tab */
  693.              pr->next = (struct tnode *)malloc(24);
  694.              free((char *)p);
  695.              p = temp->next = pr->next;
  696.           } 
  697. }    
  698.  
  699.  
  700. strcomp(s1,s2)
  701. char s1[],s2[];
  702. {
  703.           int i;
  704.  
  705.           i = 0;
  706.           while (s1[i] == s2[i])
  707.              if (s1[i++] == '\0' || i == 8)
  708.                 return 0;
  709.           return s1[i] - s2[i];
  710. }
  711.